package trend;

/* @Date 03 March 2008
 * @Author Hussein Patwa
 * Class for the main Local trending algorithm (Fig 7 on KDD paper)
 */

import java.util.*;
import java.lang.Double;

@SuppressWarnings("all")
public class Local {
    HashSet posTrend = new HashSet(); // container for negative trends
    HashSet negTrend = new HashSet(); // container for positive trends
    HashSet paths;// = new HashSet();// = new HashSet(values); // set
		    // containing paths from values array (PROBLEM!)
    // HashSet obs = new HashSet(); // container for observations
    int minlength; // min length above which trend is considered established
    int maxlength; // max length above which trend is assumed

    ArrayList path; // an array to hold the spatialobjects comprising the path

    class observation {
	double dist; // distance from x co-ordinate
	double diff; // distance from Y co-ordinate

	observation(double dist, double diff) {
	    this.dist = dist;
	    this.diff = diff;
	}
    }

    public Local(NeighbourhoodInfo neighbourInfo, ArrayList data, int index,
	    int minLength, int maxLength, double min_conf) {
	paths = computeAllPaths(neighbourInfo, index, minLength);
	// System.out.println("Number of Paths: "+paths.size());
	findTrends(index, data);
    }

    HashSet computeAllPaths(NeighbourhoodInfo neighbourInfo, int index,
	    int minLength) {
	// compute all the paths from the spatial object
	// specified by the index using the neighbourhood information
	HashSet rtn = new HashSet();
	Vector tempNeighbours = neighbourInfo.getNeighbourhoodAreaIDs(index);
	// System.out.println("index: "+index+" neighbours : "+tempNeighbours);
	for (Iterator i = tempNeighbours.iterator(); i.hasNext();) {
	    Integer node = (Integer) i.next();
	    ArrayList tempPath = new ArrayList(new Integer(index));
	    tempPath.add(new Integer(node));
	    rtn.add(tempPath);
	    // System.out.println(tempPath);
	}
	for (int j = 0; j < minLength; j++)
	    rtn.addAll(extendPath(rtn, neighbourInfo));
	return rtn;
    }

    HashSet extendPath(HashSet paths, NeighbourhoodInfo neighbourInfo) {
	HashSet rtn = new HashSet();
	for (Iterator k = paths.iterator(); k.hasNext();) {
	    ArrayList path = (ArrayList) k.next();
	    int index = ((Integer) path.get(path.size() - 1)).intValue();
	    Vector tempNeighbours = neighbourInfo
		    .getNeighbourhoodAreaIDs(index);
	    // System.out.println("index: "+index+" neighbours :
	    // "+tempNeighbours);
	    for (Iterator i = tempNeighbours.iterator(); i.hasNext();) {
		Integer node = (Integer) i.next();
		if (!path.contains(node)) {
		    ArrayList tempPath = new ArrayList();
		    tempPath.addAll(path);
		    tempPath.add(node);
		    rtn.add(tempPath);
		    // System.out.println(tempPath);
		}
	    }
	}
	return rtn;
    }

    public void findTrends(int index, ArrayList data) {
	for (Iterator i = paths.iterator(); i.hasNext();) {
	    path = (ArrayList) i.next(); // Move first element of paths to
					    // path
	    TreeMap PathObs = new TreeMap();
	    for (int j = minlength; j < path.size(); j++) // initialise
							    // counter that will
							    // track through the
							    // colums of the set
							    // paths
	    {
		// System.out.println(path.size());
		Integer currentIndex = (Integer) path.get(j);
		Spatialobject o = (Spatialobject) data.get(index);
		Spatialobject object = (Spatialobject) data.get(currentIndex);
		double dist = Math.sqrt(Math.pow((object.getX() - o.getX()), 2)
			+ Math.pow((object.getY() - o.getY()), 2)); // calculate
								    // the
								    // difference
								    // in the x
								    // co-ordinate
		double diff = object.getV() - o.getV(); // calculate the
							// difference in the y
							// co-ordinate
		// observation obsTemp = new observation(dist,diff); // insert
		// distX into observations
		PathObs.put(dist, diff);// insert distY into observations
		TreeMap predObs = getRegressionPredictions(PathObs);
		// System.out.println(PathObs+" "+predObs);

		TreeMap test = getTreeMapOfObservedAndPredicted(PathObs,
			predObs);

		
	    

	}
    }

    TreeMap getTreeMapOfObservedAndPredicted(TreeMap obs, TreeMap pred) {
	TreeMap rtn = new TreeMap();
	for (Iterator i = obs.entrySet().iterator(); i.hasNext();) {
	    Map.Entry e = (Map.Entry) i.next();
	    Double key = (Double) e.getKey();
	    Double tempObs = (Double) obs.get(key);
	    Double tempPred = (Double) pred.get(key);
	    rtn.put(tempObs, tempPred);
	}
	return rtn;
    }

    // Sample example of Wikipedia Correlation pseudo code from
    // http://64.233.183.104/search?q=cache:f6bQ8-bRWQsJ:snippetsnap.com/snippets/4720-calculate-the-Pearson-s-correlation-in-JAVA+java+implementation+pearson+correlation&hl=en&ct=clnk&cd=3&gl=uk
    public static double getPearsonCorrelation(double[] scores1,double[] scores2){        
	double result = 0;        
	double sum_sq_x = 0;        
	double sum_sq_y = 0;        
	double sum_coproduct = 0;        
	double mean_x = scores1[0];        
	double mean_y = scores2[0];        
	for(int i=2;i<scores1.length+1;i+=1){            
	    double sweep =Double.valueOf(i-1)/i;            
	    double delta_x = scores1[i-1]-mean_x;            
	    double delta_y = scores2[i-1]-mean_y;            
	    sum_sq_x += delta_x * delta_x * sweep;            
	    sum_sq_y += delta_y * delta_y * sweep;            
	    sum_coproduct += delta_x * delta_y * sweep;            
	    mean_x += delta_x / i;            
	    mean_y += delta_y / i;        }        
	double pop_sd_x = (double) Math.sqrt(sum_sq_x/scores1.length);        
	double pop_sd_y = (double) Math.sqrt(sum_sq_y/scores1.length);        
	double cov_x_y = sum_coproduct / scores1.length;        
	result = cov_x_y / (pop_sd_x*pop_sd_y);        
    return result;    }

    

    // Method to show pos or neg trend set
    public void viewTrend(String trendDir) {
    }

}
